package main

import (
	"fmt"
	"image"
	"image/color"
	"io"
	"strings"
	"time"
)

// Stringer 是一个可以用字符串描述自己的类型。fmt 包（还有很多包）都通过此接口来打印值。
func main() {
	Stringers() //	输出接口
	Errors()    //错误接口
	Readers()   //数据读取接口
	Images()    //图像接口
}

// ------------------------------------------------------------------------------------\\
func Stringers() {
	a := Person{"Arthur Dent", 42}
	z := Person{"Zaphod Beeblebrox", 9001}
	fmt.Println(a, z)
}

type Person struct {
	Name string
	Age  int
}

func (p Person) String() string {
	return fmt.Sprintf("%v (%v years)\n", p.Name, p.Age)
}

// =============================================================================================\\

// Go 程序使用 error 值来表示错误状态。fmt 包会根据对 error 的实现来打印值
// 通常函数会返回一个 error 值，调用它的代码应当判断这个错误是否等于 nil 来进行错误处理。
// error 为 nil 时表示成功；非 nil 的 error 表示失败。
func Errors() {
	fmt.Println()

	if err := run(); err != nil {
		fmt.Println(err)
		fmt.Println()
	}

	//错误练习
	fmt.Println(Sqrt(2))
	fmt.Println(Sqrt(-2))
}

type MyError struct {
	the_time  time.Time
	the_thing string
}

func (e *MyError) Error() string {
	return fmt.Sprintf("at (%v), %s", e.the_time, e.the_thing)
}

func run() error {
	return &MyError{
		time.Now(),
		"it didn't work",
	}
}

// Sqrt 接受到一个负数时，应当返回一个非 nil 的错误值。复数同样也不被支持。
type er float64

func (e er) Error() string {
	return fmt.Sprintf("cannot Sqrt negative number: %v", float64(e))
}

func Sqrt(x float64) (float64, error) {

	if x < 0 {
		return 0, er(x)
	}

	var z float64 = 1.0
	for i := 0; i < 10; i++ {
		z -= (z*z - x) / (2 * z)
	}
	return z, nil
}

//========================================================================================\\

// io 包指定了 io.Reader 接口，它表示数据流的读取端。
// Read 用数据填充给定的字节切片并返回填充的字节数和错误值。在遇到数据流的结尾时，它会返回一个 io.EOF 错误。
func Readers() {
	fmt.Println()

	//创建了一个 strings.Reader 并以每次 8 字节的速度读取它的输出

	r := strings.NewReader("hello world") //输入字符串返回 Reader 接口

	b := make([]byte, 8) //创建缓冲流空间
	for {
		n, err := r.Read(b)                                 //每次读取 b 空间字节
		fmt.Printf("n = %v, err = %v, b = %v\n", n, err, b) // n -> 读取的字节数; err -> 是否遇到结束符; b -> 读取到的值(整数值)
		fmt.Printf("b[:n]= %q\n", b[:n])                    // b[:n] -> 输出 (从0到n) 读取到的值(字符串)

		//如果是读取到结束符退出
		if err == io.EOF {
			break
		}
	}
}

// ========================================================================================\\

/*
	type Image interface {
	    ColorModel() color.Model  //颜色模式
	    Bounds() Rectangle	//图片边界
	    At(x, y int) color.Color  //图像上某个点的颜色
	}
*/
func Images() {
}

type Image struct{}

func (i Image) ColorModel() color.Model {
	return color.RGBAModel
}

func (i Image) Bounds() image.Rectangle {
	return image.Rect(0, 0, 200, 200)
}

func (i Image) At(x, y int) color.Color {
	return color.RGBA{uint8(x), uint8(y), uint8(255), uint8(255)}
}
